--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
tests/backend/test_display_name_fuzzing.py v4.6.0-rc.2 (7bbe9846) Text, 4.76 KB
T8b949e# SPDX-License-Identifier: 0BSD
Tff7b72import T7ee787base64
Tff7b72import T7ee787RNST7ee787.T7ee787vendorT7ee787.T7ee787umsgpack Tff7b72as T7ee787msgpack
Tff7b72from T7ee787hypothesis Tff7b72import Te6edf3HealthCheckTb4b4b4, Te6edf3givenTb4b4b4, Te6edf3settings
Tff7b72from T7ee787hypothesis Tff7b72import Te6edf3strategies Tff7b72as Te6edf3st
Tff7b72from T7ee787meshchatxT7ee787.T7ee787srcT7ee787.T7ee787backendT7ee787.T7ee787meshchat_utils Tff7b72import Tb4b4b4(
Te6edf3parse_lxmf_display_nameTb4b4b4,
Te6edf3parse_lxmf_propagation_node_app_dataTb4b4b4,
Te6edf3parse_lxmf_stamp_costTb4b4b4,
Te6edf3parse_nomadnetwork_node_display_nameTb4b4b4,
Tb4b4b4)
T8b949e# Strategies for generating diverse display names
Te6edf3st_display_name Tff7b72= Te6edf3stTff7b72.Td2a8ffone_ofTb4b4b4(
Te6edf3stTff7b72.Td2a8fftextTb4b4b4(Tb4b4b4)Tb4b4b4,
Te6edf3stTff7b72.Td2a8ffbinaryTb4b4b4(Tb4b4b4)Tb4b4b4,
Te6edf3stTff7b72.Td2a8ffnoneTb4b4b4(Tb4b4b4)Tb4b4b4,
Te6edf3stTff7b72.Td2a8ffintegersTb4b4b4(Te6edf3min_valueTff7b72=Tff7b72-Tb4b4b4(T79c0ff2Tff7b72*Tff7b72*T79c0ff31Tb4b4b4)Tb4b4b4, Te6edf3max_valueTff7b72=T79c0ff2Tff7b72*Tff7b72*T79c0ff31 Tff7b72- T79c0ff1Tb4b4b4)Tb4b4b4,
Te6edf3stTff7b72.Td2a8fffloatsTb4b4b4(Te6edf3allow_nanTff7b72=Tff7b72FalseTb4b4b4, Te6edf3allow_infinityTff7b72=Tff7b72FalseTb4b4b4)Tb4b4b4,
Te6edf3stTff7b72.Td2a8fflistsTb4b4b4(Te6edf3stTff7b72.Td2a8fftextTb4b4b4(Tb4b4b4)Tb4b4b4)Tb4b4b4,
Te6edf3stTff7b72.Td2a8ffdictionariesTb4b4b4(Te6edf3stTff7b72.Td2a8fftextTb4b4b4(Tb4b4b4)Tb4b4b4, Te6edf3stTff7b72.Td2a8fftextTb4b4b4(Tb4b4b4)Tb4b4b4)Tb4b4b4,
Tb4b4b4)
Tf0883e@stTff7b72.Td2a8ffcomposite
Tff7b72def Td2a8ffst_lxmf_announce_app_dataTb4b4b4(Te6edf3drawTb4b4b4)Tb4b4b4:
T8b949e"""Generates valid LXMF announce app_data (msgpack list [name, ...])."""
Te6edf3name Tff7b72= Te6edf3drawTb4b4b4(Te6edf3st_display_nameTb4b4b4)
T8b949e# LXMF announces are usually [display_name, stamp_cost, propagation_node_data, ...]
T8b949e# We'll generate lists of various lengths
Te6edf3app_data_list Tff7b72= Tb4b4b4[Te6edf3nameTb4b4b4]
Te6edf3extra_count Tff7b72= Te6edf3drawTb4b4b4(Te6edf3stTff7b72.Td2a8ffintegersTb4b4b4(Te6edf3min_valueTff7b72=T79c0ff0Tb4b4b4, Te6edf3max_valueTff7b72=T79c0ff5Tb4b4b4)Tb4b4b4)
Te6edf3app_data_listTff7b72.Td2a8ffextendTb4b4b4(Te6edf3drawTb4b4b4(Te6edf3st_display_nameTb4b4b4) Tff7b72for Te6edf3_ Tff7b72in Tffa657rangeTb4b4b4(Te6edf3extra_countTb4b4b4)Tb4b4b4)
Tff7b72return Te6edf3msgpackTff7b72.Td2a8ffpackbTb4b4b4(Te6edf3app_data_listTb4b4b4)
Tf0883e@settingsTb4b4b4(Te6edf3suppress_health_checkTff7b72=Tb4b4b4[Te6edf3HealthCheckTff7b72.Td2a8fftoo_slowTb4b4b4]Tb4b4b4)
Tf0883e@givenTb4b4b4(Te6edf3dataTff7b72=Te6edf3stTff7b72.Td2a8ffone_ofTb4b4b4(Te6edf3stTff7b72.Td2a8ffbinaryTb4b4b4(Tb4b4b4)Tb4b4b4, Te6edf3st_lxmf_announce_app_dataTb4b4b4(Tb4b4b4)Tb4b4b4)Tb4b4b4)
Tff7b72def Td2a8fftest_parse_lxmf_display_name_property_basedTb4b4b4(Te6edf3dataTb4b4b4)Tb4b4b4:
T8b949e# Test with bytes directly
Te6edf3result Tff7b72= Te6edf3parse_lxmf_display_nameTb4b4b4(Te6edf3dataTb4b4b4)
Tff7b72assert Tffa657isinstanceTb4b4b4(Te6edf3resultTb4b4b4, Tffa657strTb4b4b4)
T8b949e# Test with base64 encoded string
Te6edf3b64_data Tff7b72= Te6edf3base64Tff7b72.Td2a8ffb64encodeTb4b4b4(Te6edf3dataTb4b4b4)Tff7b72.Td2a8ffdecodeTb4b4b4(Ta5d6ff"Ta5d6ffutf-8Ta5d6ff"Tb4b4b4)
Te6edf3result_b64 Tff7b72= Te6edf3parse_lxmf_display_nameTb4b4b4(Te6edf3b64_dataTb4b4b4)
Tff7b72assert Tffa657isinstanceTb4b4b4(Te6edf3result_b64Tb4b4b4, Tffa657strTb4b4b4)
Tff7b72assert Te6edf3result Tff7b72== Te6edf3result_b64
Tf0883e@givenTb4b4b4(Te6edf3nameTff7b72=Te6edf3stTff7b72.Td2a8fftextTb4b4b4(Tb4b4b4)Tb4b4b4)
Tff7b72def Td2a8fftest_parse_nomadnetwork_node_display_name_property_basedTb4b4b4(Te6edf3nameTb4b4b4)Tb4b4b4:
T8b949e# Valid UTF-8 bytes
Te6edf3data Tff7b72= Te6edf3nameTff7b72.Td2a8ffencodeTb4b4b4(Ta5d6ff"Ta5d6ffutf-8Ta5d6ff"Tb4b4b4, Te6edf3errorsTff7b72=Ta5d6ff"Ta5d6ffreplaceTa5d6ff"Tb4b4b4)
Te6edf3result Tff7b72= Te6edf3parse_nomadnetwork_node_display_nameTb4b4b4(Te6edf3dataTb4b4b4)
Tff7b72assert Tffa657isinstanceTb4b4b4(Te6edf3resultTb4b4b4, Tffa657strTb4b4b4)
T8b949e# It might not match perfectly if there were replacement characters, but it should be a string
T8b949e# Test with base64
Te6edf3b64_data Tff7b72= Te6edf3base64Tff7b72.Td2a8ffb64encodeTb4b4b4(Te6edf3dataTb4b4b4)Tff7b72.Td2a8ffdecodeTb4b4b4(Ta5d6ff"Ta5d6ffutf-8Ta5d6ff"Tb4b4b4)
Te6edf3result_b64 Tff7b72= Te6edf3parse_nomadnetwork_node_display_nameTb4b4b4(Te6edf3b64_dataTb4b4b4)
Tff7b72assert Tffa657isinstanceTb4b4b4(Te6edf3result_b64Tb4b4b4, Tffa657strTb4b4b4)
Tff7b72assert Te6edf3result Tff7b72== Te6edf3result_b64
Tf0883e@givenTb4b4b4(Te6edf3dataTff7b72=Te6edf3stTff7b72.Td2a8ffbinaryTb4b4b4(Tb4b4b4)Tb4b4b4)
Tff7b72def Td2a8fftest_parse_lxmf_display_name_invalid_base64Tb4b4b4(Te6edf3dataTb4b4b4)Tb4b4b4:
T8b949e# Generate something that is NOT valid base64 (by adding invalid chars)
Te6edf3invalid_b64 Tff7b72= Te6edf3base64Tff7b72.Td2a8ffb64encodeTb4b4b4(Te6edf3dataTb4b4b4)Tff7b72.Td2a8ffdecodeTb4b4b4(Ta5d6ff"Ta5d6ffutf-8Ta5d6ff"Tb4b4b4) Tff7b72+ Ta5d6ff"Ta5d6ff!!!Ta5d6ff"
Te6edf3result Tff7b72= Te6edf3parse_lxmf_display_nameTb4b4b4(Te6edf3invalid_b64Tb4b4b4)
Tff7b72assert Tffa657isinstanceTb4b4b4(Te6edf3resultTb4b4b4, Tffa657strTb4b4b4)
Tf0883e@givenTb4b4b4(Te6edf3app_dataTff7b72=Te6edf3st_lxmf_announce_app_dataTb4b4b4(Tb4b4b4)Tb4b4b4)
Tff7b72def Td2a8fftest_parse_lxmf_display_name_logic_checkTb4b4b4(Te6edf3app_dataTb4b4b4)Tb4b4b4:
T8b949e"""Verify that if we can manually unpack it, parse_lxmf_display_name matches our expectation."""
Tff7b72tryTb4b4b4:
Te6edf3unpacked Tff7b72= Te6edf3msgpackTff7b72.Td2a8ffunpackbTb4b4b4(Te6edf3app_dataTb4b4b4)
Tff7b72if Tffa657isinstanceTb4b4b4(Te6edf3unpackedTb4b4b4, Tffa657listTb4b4b4) Tff7b72and Tffa657lenTb4b4b4(Te6edf3unpackedTb4b4b4) Tff7b72>Tff7b72= T79c0ff1Tb4b4b4:
Te6edf3expected_raw Tff7b72= Te6edf3unpackedTb4b4b4[T79c0ff0Tb4b4b4]
Te6edf3result Tff7b72= Te6edf3parse_lxmf_display_nameTb4b4b4(Te6edf3app_dataTb4b4b4)
Tff7b72if Te6edf3expected_raw Tff7b72is Tff7b72NoneTb4b4b4:
Tff7b72assert Te6edf3result Tff7b72== Ta5d6ff"Ta5d6ffAnonymous PeerTa5d6ff"
Tff7b72elseTb4b4b4:
T8b949e# Our implementation handles both bytes and strings, and uses errors='replace'
Tff7b72if Tffa657isinstanceTb4b4b4(Te6edf3expected_rawTb4b4b4, Tffa657bytesTb4b4b4)Tb4b4b4:
Te6edf3expected_str Tff7b72= Te6edf3expected_rawTff7b72.Td2a8ffdecodeTb4b4b4(Ta5d6ff"Ta5d6ffutf-8Ta5d6ff"Tb4b4b4, Te6edf3errorsTff7b72=Ta5d6ff"Ta5d6ffreplaceTa5d6ff"Tb4b4b4)
Tff7b72elseTb4b4b4:
Te6edf3expected_str Tff7b72= Tffa657strTb4b4b4(Te6edf3expected_rawTb4b4b4)
Tff7b72assert Te6edf3result Tff7b72== Te6edf3expected_str
Tff7b72except Tf85149ExceptionTb4b4b4:
T8b949e# If msgpack fails to unpack, the function should still return a string
Te6edf3result Tff7b72= Te6edf3parse_lxmf_display_nameTb4b4b4(Te6edf3app_dataTb4b4b4)
Tff7b72assert Tffa657isinstanceTb4b4b4(Te6edf3resultTb4b4b4, Tffa657strTb4b4b4)
Tf0883e@givenTb4b4b4(Te6edf3dataTff7b72=Te6edf3stTff7b72.Td2a8ffbinaryTb4b4b4(Te6edf3min_sizeTff7b72=T79c0ff0Tb4b4b4, Te6edf3max_sizeTff7b72=T79c0ff10000Tb4b4b4)Tb4b4b4)
Tff7b72def Td2a8fftest_parse_nomadnetwork_node_display_name_fuzzTb4b4b4(Te6edf3dataTb4b4b4)Tb4b4b4:
T8b949e# Should never crash even with completely random bytes
Te6edf3result Tff7b72= Te6edf3parse_nomadnetwork_node_display_nameTb4b4b4(Te6edf3dataTb4b4b4)
Tff7b72assert Tffa657isinstanceTb4b4b4(Te6edf3resultTb4b4b4, Tffa657strTb4b4b4)
Tf0883e@givenTb4b4b4(Te6edf3nameTff7b72=Te6edf3stTff7b72.Td2a8fftextTb4b4b4(Te6edf3min_sizeTff7b72=T79c0ff0Tb4b4b4, Te6edf3max_sizeTff7b72=T79c0ff10000Tb4b4b4)Tb4b4b4)
Tff7b72def Td2a8fftest_parse_lxmf_display_name_very_longTb4b4b4(Te6edf3nameTb4b4b4)Tb4b4b4:
T8b949e# Test with very long names
Te6edf3app_data Tff7b72= Te6edf3msgpackTff7b72.Td2a8ffpackbTb4b4b4(Tb4b4b4[Te6edf3nameTb4b4b4, Tff7b72NoneTb4b4b4, Tff7b72NoneTb4b4b4]Tb4b4b4)
Te6edf3result Tff7b72= Te6edf3parse_lxmf_display_nameTb4b4b4(Te6edf3app_dataTb4b4b4)
Tff7b72assert Te6edf3result Tff7b72== Te6edf3name
Tff7b72assert Tffa657lenTb4b4b4(Te6edf3resultTb4b4b4) Tff7b72== Tffa657lenTb4b4b4(Te6edf3nameTb4b4b4)
Tf0883e@givenTb4b4b4(Te6edf3dataTff7b72=Te6edf3stTff7b72.Td2a8ffbinaryTb4b4b4(Tb4b4b4)Tb4b4b4)
Tff7b72def Td2a8fftest_parse_lxmf_propagation_node_app_data_fuzzTb4b4b4(Te6edf3dataTb4b4b4)Tb4b4b4:
T8b949e# Should never crash
Te6edf3result Tff7b72= Te6edf3parse_lxmf_propagation_node_app_dataTb4b4b4(Te6edf3dataTb4b4b4)
Tff7b72if Te6edf3result Tff7b72is Tff7b72not Tff7b72NoneTb4b4b4:
Tff7b72assert Tffa657isinstanceTb4b4b4(Te6edf3resultTb4b4b4, Tffa657dictTb4b4b4)
Tff7b72assert Ta5d6ff"Ta5d6ffenabledTa5d6ff" Tff7b72in Te6edf3result
Tff7b72assert Ta5d6ff"Ta5d6fftimebaseTa5d6ff" Tff7b72in Te6edf3result
Tff7b72assert Ta5d6ff"Ta5d6ffper_transfer_limitTa5d6ff" Tff7b72in Te6edf3result
Tf0883e@givenTb4b4b4(Te6edf3dataTff7b72=Te6edf3stTff7b72.Td2a8ffbinaryTb4b4b4(Tb4b4b4)Tb4b4b4)
Tff7b72def Td2a8fftest_parse_lxmf_stamp_cost_fuzzTb4b4b4(Te6edf3dataTb4b4b4)Tb4b4b4:
T8b949e# Should never crash
Te6edf3parse_lxmf_stamp_costTb4b4b4(Te6edf3dataTb4b4b4)
T8b949e# stamp_cost can be None or an integer (or whatever LXMF returns)
T8b949e# We just want to ensure no crash
──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────